package org.bhf.service;

/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */

import org.bhf.json.JSONWriter;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * <code>EventQueue</code>s for queue events that will be dispatched when control returns to the client.
 */
public class EventQueue
{
    private static ThreadLocal<List<Event>> eventQueue = new ThreadLocal<List<Event>>()
    {
         protected synchronized List<Event> initialValue()
         {
             return new ArrayList<Event>( 16 );
         }
     };

    /**
     * Create a new <code>EventQueue</code> for this request: maintained as a <code>ThreadLocal</code>. Events are
     * queued, by invoking the interface operations, to be dispatched when control returns to the client. Note that
     * this interface <strong>MUST</code> match the interface given in the <code>eventGroup</code> parameter of the
     * <code>ComponentInfo</code> for this <code>Component</code>.
     *
     * @param t Interface representing the Event Group
     * @return A new <code>EventQueue</code>
     */
    public static <T> T getNewQueue( Class<T> t )
    {
        eventQueue.get().clear();

        final Object o = Proxy.newProxyInstance(
            Thread.currentThread().getContextClassLoader(),
            new Class[] { t },
            new InvocationHandler()
            {
                public Object invoke( final Object object, final Method method, final Object[] objects )
                    throws IOException
                {
                    final Event event = new Event( method.getName(), objects != null && objects.length > 0 ? new JSONWriter().writeObject( objects ) : null );
                    eventQueue.get().add( event );
                    return null;
                }
            }
        );

        return t.cast( o );
    }

    /**
     * Return the <code>EventQueue</code> associated with this <code>Thread</code>.
     * @return the <code>EventQueue</code> associated with this <code>Thread</code>.
     * @exclude
     */
    public static List<Event>   getEvents()
    {
        return eventQueue.get();
    }

    /**
     * Will be JSON marshalled on return
     * @exclude
     */
    public static class Event
    {
        final String    event;
        final String    o;

        Event( final String event, final String o )
        {
            this.event  = event;
            this.o      = o;
        }

        public String getEvent()
        {
            return event;
        }

        public String getO()
        {
            return o;
        }
    }
}